home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1994…tember: Reference Library / Dev.CD Sep 94.toast / Periodicals / develop / develop Issue 6 / develop 6 code / TCP / NewsWatcher / NewsWatcher 2.0d15 source / source / print.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-07-17  |  7.9 KB  |  351 lines  |  [TEXT/KAHL]

  1. /*----------------------------------------------------------------------------
  2.  
  3.     print.c
  4.  
  5.     This module handles printing.
  6.     
  7.     Portions copyright © 1990, Apple Computer.
  8.     Portions copyright © 1993, Northwestern University.
  9.  
  10. ----------------------------------------------------------------------------*/
  11.  
  12. #include <Printing.h>
  13.  
  14. #include "dlgutil.h"
  15. #include "glob.h"
  16. #include "print.h"
  17. #include "save.h"
  18. #include "util.h"
  19.  
  20.  
  21. #define odd(theInt) ( (theInt % 2) == 1 )
  22.  
  23. static THPrint myHPrint;        /* printing handle */
  24. static TEHandle printTE;        /* textedit handle to print */
  25. static Handle txt;                /* text to print */
  26. static short linesPerPage;        /* # of lines per page */
  27. static long numLines;            /* total # lines */
  28.  
  29. static TPPrPort        prPort;        /* printing port */
  30. static Boolean        prIsOpen,docIsOpen,pageIsOpen;    /* printing flags */
  31.  
  32. /* Globals for printing segmented article windows. */
  33.  
  34. static Boolean segmented;            /* true if segmented */
  35. static short numSections;            /* number of sections */
  36. static short curSection;            /* current section in printTE, or -1 if none */
  37. static long **sectionBreaks;        /* handle to array of section breaks */
  38. static long **firstLines;            /* handle to array of section first line numbers */
  39.  
  40.  
  41. static void CleanUp (void)
  42. {
  43.     MyIOCheck(PrError());
  44.     if (pageIsOpen)
  45.         PrClosePage(prPort);
  46.     if (docIsOpen)
  47.         PrCloseDoc(prPort);
  48.     if (prIsOpen)
  49.         PrClose();
  50. }
  51.  
  52. /*    PrepSegmented prepares for printing segmented article windows. It calculates
  53.     the firstLines array and the total number of lines.
  54. */
  55.  
  56. static void PrepSegmented (void)
  57. {
  58.     long linesInSection,offset,length;
  59.     short i;
  60.  
  61.     HLock(txt);
  62.     for (i = numSections-1; i >= 0; i--) {
  63.         offset = (*sectionBreaks)[i];
  64.         length = (*sectionBreaks)[i+1] - offset;
  65.         TESetText(*txt+offset,length,printTE);
  66.         (*firstLines)[i] = (**printTE).nLines;
  67.     }
  68.     HUnlock(txt);
  69.     
  70.     numLines = 0;
  71.     for (i = 0; i < numSections; i++) {
  72.         linesInSection = (*firstLines)[i];
  73.         (*firstLines)[i] = numLines;
  74.         numLines += linesInSection;
  75.     }
  76.     (*firstLines)[numSections] = numLines;
  77.     curSection = 0;
  78. }
  79.  
  80. /*    MyPrepProc prepares for printing.
  81. */
  82.  
  83. static Boolean MyPrepProc (THPrint theHPrint)
  84. {
  85.     short numPages;
  86.  
  87.     linesPerPage = ((**theHPrint).prInfo.rPage.bottom - (**theHPrint).prInfo.rPage.top) / (**printTE).lineHeight;
  88.  
  89.     if (segmented) {
  90.         PrepSegmented();
  91.     } else {
  92.         numLines = (**printTE).nLines;
  93.     }
  94.     numPages = (numLines + linesPerPage - 1) / linesPerPage;
  95.     
  96.     if ((**theHPrint).prJob.iLstPage > numPages)
  97.         (**theHPrint).prJob.iLstPage = numPages;
  98.     if ( (**theHPrint).prJob.iLstPage >= (**theHPrint).prJob.iFstPage ) {
  99.         return(true);
  100.     } else {
  101.         ErrorMessage("There are no pages in the range you specified.");
  102.         return(false);
  103.     }
  104. }
  105.  
  106. /*    MyPageProc prints one page.
  107. */
  108.  
  109. static Boolean MyPageProc (THPrint theHPrint,Rect *drawRect,short pageNum)
  110. {
  111.     short vCoord = drawRect->top + (**printTE).fontAscent;
  112.     long line, lastLine, length;
  113.     long offset = 0;
  114.     long firstLineThisSection = 0;
  115.     long firstLineNextSection;
  116.     short start,next;
  117.     short i;
  118.     char *sectionStart;
  119.     
  120.     HLock(txt);
  121.     TextFont((**printTE).txFont);
  122.     TextFace((**printTE).txFace);
  123.     TextMode((**printTE).txMode);
  124.     TextSize((**printTE).txSize);
  125.         
  126.     line = ((pageNum - 1) * linesPerPage);    /*    LSR: starting line #    */
  127.     
  128.     if (line + linesPerPage > numLines)
  129.         lastLine = numLines;
  130.     else
  131.         lastLine = line + linesPerPage;
  132.     
  133.     if (segmented) {
  134.         for (i = 0; i < numSections && line >= (*firstLines)[i]; i++);
  135.         i--;
  136.         offset = (*sectionBreaks)[i];
  137.         sectionStart = *txt + offset;
  138.         firstLineThisSection = (*firstLines)[i];
  139.         firstLineNextSection = (*firstLines)[i+1];
  140.         if (i != curSection) {
  141.             length = (*sectionBreaks)[i+1] - offset;
  142.             TESetText(sectionStart,length,printTE);
  143.             curSection = i;
  144.         }
  145.     } else {
  146.         sectionStart = *txt;
  147.     }
  148.     
  149.     start = (**printTE).lineStarts[line-firstLineThisSection];
  150.     
  151.     while (true) {
  152.         if (line-firstLineThisSection < (**printTE).nLines-1)
  153.             next = (**printTE).lineStarts[line+1-firstLineThisSection];
  154.         else
  155.             next = (**printTE).teLength;
  156.         /*    LSR: next is offset to next char to print    */
  157.         
  158.         MoveTo(drawRect->left, vCoord);
  159.         DrawText(sectionStart, start, next-start);
  160.         line++;
  161.         if (line == lastLine) break;
  162.         
  163.         start = next;
  164.         if (segmented && line >= firstLineNextSection) {
  165.             curSection++;
  166.             offset = (*sectionBreaks)[curSection];
  167.             sectionStart = *txt + offset;
  168.             length = (*sectionBreaks)[curSection+1] - offset;
  169.             TESetText(sectionStart,length,printTE);
  170.             firstLineThisSection = firstLineNextSection;
  171.             firstLineNextSection = (*firstLines)[curSection+1];
  172.             start = 0;
  173.         }
  174.  
  175.         vCoord += (**printTE).lineHeight;
  176.     }
  177.  
  178.     HUnlock(txt);
  179.     return(true);
  180. }
  181.  
  182. /*    ExecutePrint is the main print control routine. */
  183.  
  184.  
  185. static OSErr ExecutePrint (THPrint hPrint)
  186. {
  187.     short theFirst,theLast;
  188.     Boolean wasnil,scratch;
  189.     short nCopies;
  190.     short prDevice;
  191.     Boolean draftMode;
  192.     TPrStatus prStatus;
  193.     GrafPtr savePort;
  194.     OSErr curPrError;
  195.     Rect pageRect;
  196.     short i,p;
  197.  
  198.     prIsOpen = docIsOpen = pageIsOpen = false;
  199.     GetPort(&savePort);
  200.     wasnil = (hPrint == nil);
  201.     PrOpen();
  202.     if (PrError() != noErr) {
  203.         SetPort(savePort);
  204.         CleanUp();
  205.         return(PrError());
  206.     }
  207.     prIsOpen = true;
  208.     scratch = PrValidate(hPrint);
  209.     if (!PrJobDialog(hPrint)) {
  210.         SetPort(savePort);
  211.         CleanUp();
  212.         return(PrError());
  213.     }
  214.     if (!MyPrepProc(hPrint)) {
  215.         SetPort(savePort);
  216.         CleanUp();
  217.         return(PrError());
  218.     }
  219.     theFirst = (**hPrint).prJob.iFstPage;
  220.     theLast = (**hPrint).prJob.iLstPage;
  221.     (**hPrint).prJob.iFstPage = 1;
  222.     (**hPrint).prJob.iLstPage = 9999;
  223.     prDevice = ( (**hPrint).prStl.wDev >> 8 );
  224.     draftMode = !(odd((**hPrint).prJob.bJDocLoop));
  225.     if ((draftMode) && (prDevice == 1))
  226.         nCopies = (**hPrint).prJob.iCopies;
  227.     else
  228.         nCopies = 1;
  229.     
  230.     prPort = PrOpenDoc(hPrint,nil,nil);
  231.     docIsOpen = true;
  232.     curPrError = PrError();
  233.     if (curPrError != noErr) {
  234.         SetPort(savePort);
  235.         return(curPrError);
  236.     }
  237.     SetPort(&prPort->gPort);
  238.     for (i=1; i<=nCopies; i++) {
  239.         for (p=theFirst; p<=theLast; p++) {
  240.             PrOpenPage(prPort,nil);
  241.             pageIsOpen = true;
  242.             HLock((Handle)hPrint);
  243.             pageRect = (**hPrint).prInfo.rPage;
  244.             scratch = MyPageProc(hPrint,&pageRect,p);
  245.             HUnlock((Handle)hPrint);
  246.             PrClosePage(prPort);
  247.             if (!scratch) {
  248.                 SetPort(savePort);
  249.                 curPrError = iPrAbort;
  250.                 CleanUp();
  251.                 return(PrError());
  252.             }
  253.         }
  254.     }
  255.     PrCloseDoc(prPort);
  256.     docIsOpen = false;
  257.     curPrError = PrError();
  258.     
  259.     if ( !draftMode && (curPrError != noErr))
  260.         PrPicFile(hPrint,nil,nil,nil,&prStatus);
  261.     curPrError = PrError();
  262.     PrClose();
  263.     prIsOpen = false;
  264.     
  265.     SetPort(savePort);
  266.     return(noErr);
  267. }
  268.  
  269. static void InitPrint (void)
  270. {
  271.     static Boolean InitDone = false;
  272.  
  273.     if (InitDone) return;
  274.     InitDone = true;
  275.     PrOpen();
  276.     MyIOCheck(PrError());
  277.     myHPrint = (THPrint) MyNewHandle(sizeof(TPrint));
  278.     if (MyMemErr() != noErr)
  279.         return;
  280.     PrintDefault(myHPrint);
  281.     MyIOCheck(PrError());
  282.     PrClose();
  283. }
  284.  
  285. void DoPageSetup (void)
  286. {
  287.     InitPrint();
  288.     InitCursor();
  289.     PrOpen();
  290.     if (PrError() == noErr) {
  291.         PrValidate(myHPrint);
  292.         if (PrError() == noErr)
  293.             PrStlDialog(myHPrint);
  294.         else MyIOCheck(PrError());
  295.     }
  296.     else
  297.         MyIOCheck(PrError());
  298.     PrClose();
  299.     MyIOCheck(PrError());
  300. }
  301.  
  302. /*    DoPrint handles printing.
  303. */
  304.  
  305. void DoPrint (WindowPtr wind)
  306. {
  307.     Handle oldText;
  308.     TWindow **info;
  309.     EWindowKind kind;
  310.     Boolean isArticle, mustDispose=false;
  311.  
  312.     InitPrint();
  313.  
  314.     info = (TWindow**)GetWRefCon(wind);
  315.     kind = (**info).kind;
  316.     isArticle = kind == kArticle || kind == kMiscArticle;
  317.     segmented = isArticle && (**info).numSections != 0;
  318.     
  319.     InitCursor();
  320.     
  321.     printTE = TENew(&(**myHPrint).prInfo.rPage, &(**myHPrint).prInfo.rPage);
  322.     
  323.     if (isArticle) {
  324.         txt = (**info).fullText;
  325.     } else {
  326.         GetFullMessageText(wind, &txt, &mustDispose);
  327.     }
  328.     
  329.     if (segmented) {
  330.         numSections = (**info).numSections;
  331.         curSection = -1;
  332.         sectionBreaks = (**info).sectionBreaks;
  333.         firstLines = (long**)MyNewHandle(sizeof(long)*(numSections+1));
  334.     } else {
  335.         oldText = (**printTE).hText;
  336.         (**printTE).hText = txt;
  337.         TECalText(printTE);
  338.     }
  339.     
  340.     MyIOCheck( ExecutePrint(myHPrint) );
  341.     
  342.     if (segmented) {
  343.         MyDisposHandle((Handle)firstLines);
  344.     } else {
  345.         (**printTE).hText = oldText;
  346.     }
  347.     TEDispose(printTE);
  348.     if (mustDispose) MyDisposHandle(txt);
  349.     printTE = NULL;
  350. }
  351.